const { db } = require('../config/leveldb');
const fs = require('fs');
const path = require('path');

class LevelDBService {
  // 工具方法：生成键名
  static generateKey(prefix, ...args) {
    return `${prefix}:${args.join(':')}`;
  }

  // 用户相关操作
  static async createUser(username, email, passwordHash, initialBalance = 0) {
    const userId = Date.now().toString(); // 使用时间戳作为简单ID
    const userData = {
      id: userId,
      username,
      email,
      password_hash: passwordHash,
      balance: initialBalance,
      created_at: new Date().toISOString(),
      updated_at: new Date().toISOString()
    };

    const userKey = this.generateKey('user', userId);
    const usernameKey = this.generateKey('username', username);
    const emailKey = this.generateKey('email', email);

    // 使用批处理确保原子性
    await db.batch([
      { type: 'put', key: userKey, value: userData },
      { type: 'put', key: usernameKey, value: userId },
      { type: 'put', key: emailKey, value: userId }
    ]);

    return userData;
  }

  static async getUserById(id) {
    try {
      const userKey = this.generateKey('user', id);
      return await db.get(userKey);
    } catch (err) {
      if (err.notFound) {
        return null;
      }
      throw err;
    }
  }

  static async getUserByUsername(username) {
    try {
      const usernameKey = this.generateKey('username', username);
      const userId = await db.get(usernameKey);
      return await this.getUserById(userId);
    } catch (err) {
      if (err.notFound) {
        return null;
      }
      throw err;
    }
  }

  static async getUserByEmail(email) {
    try {
      const emailKey = this.generateKey('email', email);
      const userId = await db.get(emailKey);
      return await this.getUserById(userId);
    } catch (err) {
      if (err.notFound) {
        return null;
      }
      throw err;
    }
  }

  static async updateUserBalance(userId, newBalance) {
    const userData = await this.getUserById(userId);
    if (!userData) {
      throw new Error('User not found');
    }

    userData.balance = newBalance;
    userData.updated_at = new Date().toISOString();

    const userKey = this.generateKey('user', userId);
    await db.put(userKey, userData);

    return userData;
  }

  // 股票相关操作
  static async createStock(symbol, name, currentPrice = 0) {
    const stockId = Date.now().toString(); // 使用时间戳作为简单ID
    const stockData = {
      id: stockId,
      symbol,
      name,
      current_price: currentPrice,
      last_updated: new Date().toISOString(),
      created_at: new Date().toISOString()
    };

    const stockKey = this.generateKey('stock', stockId);
    const symbolKey = this.generateKey('stock_symbol', symbol);

    // 使用批处理确保原子性
    await db.batch([
      { type: 'put', key: stockKey, value: stockData },
      { type: 'put', key: symbolKey, value: stockId }
    ]);

    return stockData;
  }

  static async getStockById(id) {
    try {
      const stockKey = this.generateKey('stock', id);
      return await db.get(stockKey);
    } catch (err) {
      if (err.notFound) {
        return null;
      }
      throw err;
    }
  }

  static async getStockBySymbol(symbol) {
    try {
      const symbolKey = this.generateKey('stock_symbol', symbol);
      const stockId = await db.get(symbolKey);
      return await this.getStockById(stockId);
    } catch (err) {
      if (err.notFound) {
        return null;
      }
      throw err;
    }
  }

  static async updateStockPrice(stockId, newPrice) {
    const stockData = await this.getStockById(stockId);
    if (!stockData) {
      throw new Error('Stock not found');
    }

    stockData.current_price = newPrice;
    stockData.last_updated = new Date().toISOString();

    const stockKey = this.generateKey('stock', stockId);
    await db.put(stockKey, stockData);

    return stockData;
  }

  // 更新股票名称
  static async updateStockName(stockId, newName) {
    const stockData = await this.getStockById(stockId);
    if (!stockData) {
      throw new Error('Stock not found');
    }

    stockData.name = newName;
    stockData.last_updated = new Date().toISOString();

    const stockKey = this.generateKey('stock', stockId);
    await db.put(stockKey, stockData);

    return stockData;
  }

  // 初始化股票信息表
  static async initializeStockInfo() {
    try {
      // 读取A股数据文件
      const aSharesData = fs.readFileSync(path.join(__dirname, '../../data/a_shares.txt'), 'utf8');
      const aShares = aSharesData.split('\n')
        .filter(line => line.trim() !== '')
        .map(line => {
          const [symbol, name, market] = line.split(',');
          return { symbol, name, market };
        });

      // 读取创业板数据文件
      const gemSharesData = fs.readFileSync(path.join(__dirname, '../../data/gem_shares.txt'), 'utf8');
      const gemShares = gemSharesData.split('\n')
        .filter(line => line.trim() !== '')
        .map(line => {
          const [symbol, name, market] = line.split(',');
          return { symbol, name, market };
        });

      // 读取港股数据文件
      const hkSharesData = fs.readFileSync(path.join(__dirname, '../../data/hk_shares.txt'), 'utf8');
      const hkShares = hkSharesData.split('\n')
        .filter(line => line.trim() !== '')
        .map(line => {
          const [symbol, name, market] = line.split(',');
          return { symbol, name, market };
        });

      // 合并所有股票
      const allStocks = [...aShares, ...gemShares, ...hkShares];

      // 批量创建股票记录
      const batch = [];
      for (const stock of allStocks) {
        // 检查是否已存在
        const existingStock = await this.getStockBySymbol(stock.symbol);
        if (!existingStock) {
          const stockId = Date.now().toString() + Math.random().toString(36).substr(2, 5);
          const stockData = {
            id: stockId,
            symbol: stock.symbol,
            name: stock.name,
            market: stock.market,
            current_price: 0,
            last_updated: new Date().toISOString(),
            created_at: new Date().toISOString()
          };

          const stockKey = this.generateKey('stock', stockId);
          const symbolKey = this.generateKey('stock_symbol', stock.symbol);

          batch.push({ type: 'put', key: stockKey, value: stockData });
          batch.push({ type: 'put', key: symbolKey, value: stockId });
        }
      }

      // 执行批量操作
      if (batch.length > 0) {
        await db.batch(batch);
      }

      console.log(`Initialized stock info table with ${allStocks.length} stocks`);
    } catch (error) {
      console.error('Error initializing stock info:', error);
    }
  }

  // 获取所有股票信息
  static async getAllStocks() {
    const stocks = [];
    const prefix = 'stock:';

    for await (const [key, value] of db.iterator({ gte: prefix, lte: prefix + '\xff' })) {
      if (key.startsWith(prefix) && !key.includes(':symbol:')) {
        stocks.push(value);
      }
    }

    return stocks.sort((a, b) => a.symbol.localeCompare(b.symbol));
  }

  // 根据市场类型获取股票
  static async getStocksByMarket(market) {
    const stocks = [];
    const prefix = 'stock:';

    for await (const [key, value] of db.iterator({ gte: prefix, lte: prefix + '\xff' })) {
      if (key.startsWith(prefix) && !key.includes(':symbol:') && value.market === market) {
        stocks.push(value);
      }
    }

    return stocks.sort((a, b) => a.symbol.localeCompare(b.symbol));
  }

  // 搜索股票（根据代码或名称）
  static async searchStocks(keyword) {
    const stocks = [];
    const prefix = 'stock:';
    const lowerKeyword = keyword.toLowerCase();

    for await (const [key, value] of db.iterator({ gte: prefix, lte: prefix + '\xff' })) {
      if (key.startsWith(prefix) && !key.includes(':symbol:')) {
        if (value.symbol.includes(keyword) || value.name.toLowerCase().includes(lowerKeyword)) {
          stocks.push(value);
        }
      }
    }

    return stocks.sort((a, b) => a.symbol.localeCompare(b.symbol));
  }

  // 交易相关操作
  static async createTrade(userId, stockId, type, quantity, price) {
    const tradeId = Date.now().toString(); // 使用时间戳作为简单ID
    const tradeData = {
      id: tradeId,
      user_id: userId,
      stock_id: stockId,
      type,
      quantity,
      price,
      status: 'PENDING',
      created_at: new Date().toISOString()
    };

    const tradeKey = this.generateKey('trade', tradeId);
    await db.put(tradeKey, tradeData);

    return tradeData;
  }

  static async getTradeById(id) {
    try {
      const tradeKey = this.generateKey('trade', id);
      const tradeData = await db.get(tradeKey);

      // 获取关联的用户和股票信息
      const userData = await this.getUserById(tradeData.user_id);
      const stockData = await this.getStockById(tradeData.stock_id);

      return {
        ...tradeData,
        username: userData ? userData.username : null,
        symbol: stockData ? stockData.symbol : null,
        stock_name: stockData ? stockData.name : null
      };
    } catch (err) {
      if (err.notFound) {
        return null;
      }
      throw err;
    }
  }

  static async getTradesByUserId(userId) {
    const trades = [];
    const prefix = 'trade:';

    for await (const [key, value] of db.iterator({ gte: prefix, lte: prefix + '\xff' })) {
      if (key.startsWith(prefix) && value.user_id === userId) {
        // 获取关联的股票信息
        const stockData = await this.getStockById(value.stock_id);
        trades.push({
          ...value,
          symbol: stockData ? stockData.symbol : null,
          stock_name: stockData ? stockData.name : null
        });
      }
    }

    return trades.sort((a, b) => new Date(b.created_at) - new Date(a.created_at));
  }

  static async getTradesByStockId(stockId) {
    const trades = [];
    const prefix = 'trade:';

    for await (const [key, value] of db.iterator({ gte: prefix, lte: prefix + '\xff' })) {
      if (key.startsWith(prefix) && value.stock_id === stockId) {
        // 获取关联的用户信息
        const userData = await this.getUserById(value.user_id);
        trades.push({
          ...value,
          username: userData ? userData.username : null
        });
      }
    }

    return trades.sort((a, b) => new Date(b.created_at) - new Date(a.created_at));
  }

  static async executeTrade(tradeId) {
    const tradeData = await this.getTradeById(tradeId);
    if (!tradeData) {
      throw new Error('Trade not found');
    }

    tradeData.status = 'EXECUTED';
    tradeData.executed_at = new Date().toISOString();

    const tradeKey = this.generateKey('trade', tradeId);
    await db.put(tradeKey, tradeData);

    return tradeData;
  }

  static async cancelTrade(tradeId) {
    const tradeData = await this.getTradeById(tradeId);
    if (!tradeData) {
      throw new Error('Trade not found');
    }

    tradeData.status = 'CANCELLED';

    const tradeKey = this.generateKey('trade', tradeId);
    await db.put(tradeKey, tradeData);

    return tradeData;
  }

  // 投资组合相关操作
  static async getPortfolioByUserId(userId) {
    const portfolio = [];
    const prefix = this.generateKey('portfolio', userId);

    for await (const [key, value] of db.iterator({ gte: prefix, lte: prefix + '\xff' })) {
      if (key.startsWith(prefix)) {
        // 获取关联的股票信息
        const stockData = await this.getStockById(value.stock_id);
        portfolio.push({
          ...value,
          symbol: stockData ? stockData.symbol : null,
          stock_name: stockData ? stockData.name : null,
          current_price: stockData ? stockData.current_price : null
        });
      }
    }

    return portfolio;
  }

  static async upsertPortfolio(userId, stockId, quantity, averagePrice) {
    const portfolioKey = this.generateKey('portfolio', userId, stockId);
    const portfolioData = {
      user_id: userId,
      stock_id: stockId,
      quantity,
      average_price: averagePrice,
      updated_at: new Date().toISOString()
    };

    await db.put(portfolioKey, portfolioData);

    return portfolioData;
  }

  static async deletePortfolioItem(userId, stockId) {
    const portfolioKey = this.generateKey('portfolio', userId, stockId);
    await db.del(portfolioKey);
  }

  // 策略相关操作
  static async createStrategy(userId, name, description, config) {
    const strategyId = Date.now().toString(); // 使用时间戳作为简单ID
    const strategyData = {
      id: strategyId,
      user_id: userId,
      name,
      description,
      config,
      is_active: true,
      created_at: new Date().toISOString(),
      updated_at: new Date().toISOString()
    };

    const strategyKey = this.generateKey('strategy', strategyId);
    await db.put(strategyKey, strategyData);

    return strategyData;
  }

  static async getStrategyById(id) {
    try {
      const strategyKey = this.generateKey('strategy', id);
      return await db.get(strategyKey);
    } catch (err) {
      if (err.notFound) {
        return null;
      }
      throw err;
    }
  }

  static async getStrategiesByUserId(userId) {
    const strategies = [];
    const prefix = 'strategy:';

    for await (const [key, value] of db.iterator({ gte: prefix, lte: prefix + '\xff' })) {
      if (key.startsWith(prefix) && value.user_id === userId) {
        strategies.push(value);
      }
    }

    return strategies.sort((a, b) => new Date(b.created_at) - new Date(a.created_at));
  }

  static async updateStrategy(id, name, description, config, isActive) {
    const strategyData = await this.getStrategyById(id);
    if (!strategyData) {
      throw new Error('Strategy not found');
    }

    strategyData.name = name;
    strategyData.description = description;
    strategyData.config = config;
    strategyData.is_active = isActive;
    strategyData.updated_at = new Date().toISOString();

    const strategyKey = this.generateKey('strategy', id);
    await db.put(strategyKey, strategyData);

    return strategyData;
  }

  static async deleteStrategy(id) {
    const strategyKey = this.generateKey('strategy', id);
    await db.del(strategyKey);
  }

  // 历史数据相关操作
  static async saveStockHistory(symbol, historyData) {
    const batch = [];
    
    for (const item of historyData) {
      const historyKey = this.generateKey('stock_history', symbol, item.date);
      batch.push({ type: 'put', key: historyKey, value: item });
    }

    await db.batch(batch);
  }

  static async getStockHistory(symbol, limit = 100) {
    const history = [];
    const prefix = this.generateKey('stock_history', symbol);

    // 由于LevelDB是有序的，我们可以通过反向迭代获取最新的数据
    for await (const [key, value] of db.iterator({ 
      gte: prefix, 
      lte: prefix + '\xff',
      reverse: true,
      limit: limit
    })) {
      if (key.startsWith(prefix)) {
        history.push(value);
      }
    }

    // 按日期正序排列
    return history.sort((a, b) => new Date(a.date) - new Date(b.date));
  }

  static async getStockHistoryByDateRange(symbol, startDate, endDate) {
    const history = [];
    const prefix = this.generateKey('stock_history', symbol);

    for await (const [key, value] of db.iterator({ gte: prefix, lte: prefix + '\xff' })) {
      if (key.startsWith(prefix)) {
        const itemDate = new Date(value.date);
        if (itemDate >= new Date(startDate) && itemDate <= new Date(endDate)) {
          history.push(value);
        }
      }
    }

    return history.sort((a, b) => new Date(a.date) - new Date(b.date));
  }
}

module.exports = LevelDBService;